module arm.trace;


/*
    调用前提是需要排位置swo方式输出调试信息
    ref:https://developer.arm.com/documentation/dui0282/b/semihosting/semihosting-swis?lang=en
*/
enum InvokeCMD:uint
{
    Open = 0x01,
    Close = 0x02,
    WriteC = 0x03,          /// 写字符
    Write0 = 0x04,          /// 写字符串,以\0x00结尾
    Write = 0x05,           /// 写到文件流
    Read = 0x06,
    ReadC = 0x07,
    IsError = 0x08,
    IsTTY = 0x09,
    Seek = 0x0A,
    FLen = 0x0C,
    TmpNam = 0x0D,
    Remove = 0x0E,
    Rename = 0x0F,
    Clock = 0x10,
    Time = 0x11,
    System = 0x12,
    Errno = 0x13,
    GetCmdLine = 0x15,
    HeapInfo = 0x16,
    Elapsed = 0x30,
    TickFreq = 0x31,
}




/*
private
void semihostingWrite(const scope void* ptr, uint length) @trusted
{
    // Create semihosting message message
    uint[3] message =
    [
        2,             // stderr
        cast(uint)ptr, // ptr to string
        length         // size of string
    ];
    semihostingInvoke(InvokeCMD.Write, &message[0]);
}
*/
private
{
    void semihostingInvoke(in InvokeCMD command, const scope void* message) @trusted
    {
        int value = void;
        /*
        asm
        {
            "mov r0, %[op]; 
            mov r1, %[msg]; 
            bkpt #0xAB;
            mov %[val], r0;"
            : [val] "=r"(value) 
            : [op] "r" (command), [msg] "r" (message)
            : "r0", "r1", "memory";
        }
*/
            asm
            {
                "mov r0, %1;
                mov r1, %2;
                bkpt #0xAB;
                mov %0, r0;"
                : "=r"(value)
                : "r" (command), "r"(message)
                : "r0", "r1", "memory";
            }
        /+
        version(LDC)
        {
            import ldc.llvmasm;
            __asm
            (
                "mov r0, $0;
                mov r1, $1;
                bkpt #0xAB,
                mov $2,r0",
                "r,r,~{r0},~{r1}",
                command, message
            );
        }else version(GDC){
            /*
            asm
            {
                "mov r0, %[cmd];
                mov r1, %[msg];
                bkpt #0xAB;"
                :
                : [cmd] "r" command, [msg] "r" message
                : "r0", "r1", "memory";
            }
            */
        }else{
            static assert(0, "Not supported compiler");
        }
        +/
    }


}

/*
void write(in string str)
{
    if(str.length > 0)
    {
        semihostingWrite(str.ptr, str.length);
        //semihostingWrite(&str[0], str.length);
    }
}
*/

void write(ubyte c)
{
    semihostingInvoke(InvokeCMD.WriteC,&c);
}

